package com.xuexiang.xui_lib.component.status;

import com.xuexiang.xui_lib.ResourceTable;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.*;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;

public class StatusComponent extends StackLayout {

    private static final int DISMISS_ON_COMPLETE_DELAY = 1000;

    private LayoutScatter mLayoutScatter;
    private Component mCompleteComponent;
    private Component mCustomComponent;
    private Component mErrorComponent;
    private Component mLoadingComponent;

    private EventHandler mHandler;
    private AnimatorProperty inAnimator;
    private AnimatorProperty outAnimator;

    private Status mCurrentStatus;
    private boolean mHideOnComplete = true;

    private Runnable mAutoDismissOnComplete = new Runnable() {
        @Override
        public void run() {
            exitAnimation(getCurrentView(mCurrentStatus));
            mHandler.removeTask(mAutoDismissOnComplete);
        }
    };

    public StatusComponent(Context context) {
        this(context, null);
    }

    public StatusComponent(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public StatusComponent(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        mLayoutScatter = LayoutScatter.getInstance(context);
        mHandler = new EventHandler(EventRunner.getMainEventRunner());
        init();
    }

    private void init() {
        mCurrentStatus = Status.NONE;
        inAnimator = createInAnimator();
        outAnimator = createOutAnimator();

        mCompleteComponent = mLayoutScatter.parse(ResourceTable.Layout_xui_sv_layout_complete, null, false);
        mCustomComponent = mLayoutScatter.parse(ResourceTable.Layout_xui_sv_layout_custom, null, false);
        mErrorComponent = mLayoutScatter.parse(ResourceTable.Layout_xui_sv_layout_error, null, false);
        mLoadingComponent = mLayoutScatter.parse(ResourceTable.Layout_xui_sv_layout_loading, null, false);

        // 添加到当前容器中并
        addComponent(mCompleteComponent, createLayoutConfig());
        addComponent(mCustomComponent, createLayoutConfig());
        addComponent(mErrorComponent, createLayoutConfig());
        addComponent(mLoadingComponent, createLayoutConfig());

        // 默认隐藏
        mCompleteComponent.setVisibility(Component.INVISIBLE);
        mCustomComponent.setVisibility(Component.INVISIBLE);
        mErrorComponent.setVisibility(Component.INVISIBLE);
        mLoadingComponent.setVisibility(Component.INVISIBLE);
    }

    private AnimatorProperty createOutAnimator() {
        AnimatorProperty property = new AnimatorProperty();
        property.setDuration(150);
        property.moveToY(-100);
        return property;
    }

    private AnimatorProperty createInAnimator() {
        AnimatorProperty property = new AnimatorProperty();
        property.moveFromY(-100);
        property.moveToY(0);
        property.setDuration(150);
        return property;
    }

    /**
     * 是否在显示完后隐藏  默认true
     *
     * @param hideOnComplete 1
     * @return 1
     */
    public StatusComponent setHideOnComplete(boolean hideOnComplete) {
        mHideOnComplete = hideOnComplete;
        return this;
    }

    /**
     * 消失
     */
    public void dismiss() {
        setStatus(Status.NONE);
    }

    /**
     * 获取当前状态
     *
     * @return Status object
     */
    public Status getStatus() {
        return mCurrentStatus;
    }

    /**
     * 设置自定义状态的标题
     *
     * @param id 1
     * @param title 1
     * @return 1
     */
    public Component setCustomViewTitle(int id, String title) {
        Component view = mCustomComponent.findComponentById(id);
        if (view instanceof Text) {
            ((Text) view).setText(title);
        }
        return view;
    }

    /**
     * 改变状态
     *
     * @param status
     */
    public void setStatus(final Status status) {
        setVisibility(VISIBLE);
        if (mCurrentStatus == Status.NONE) {
            mCurrentStatus = status;
            enterAnimation(getCurrentView(mCurrentStatus));
        } else if (status != Status.NONE) {
            switchAnimation(getCurrentView(mCurrentStatus), getCurrentView(status));
            mCurrentStatus = status;
        } else {
            exitAnimation(getCurrentView(mCurrentStatus));
        }
        mHandler.removeAllEvent();
        if (status == Status.COMPLETE && mHideOnComplete) {
            mHandler.postTask(mAutoDismissOnComplete, DISMISS_ON_COMPLETE_DELAY);
        }
    }

    public void setOnErrorClickListener(ClickedListener onErrorClickListener) {
        mErrorComponent.setClickedListener(onErrorClickListener);
    }

    public void setOnCustomClickListener(ClickedListener onErrorClickListener) {
        mCustomComponent.setClickedListener(onErrorClickListener);
    }

    public void setOnLoadingClickListener(ClickedListener onLoadingClickListener) {
        mLoadingComponent.setClickedListener(onLoadingClickListener);
    }

    public void setOnCompleteClickListener(ClickedListener onCompleteClickListener) {
        mCompleteComponent.setClickedListener(onCompleteClickListener);
    }

    public Component getErrorView() {
        return mErrorComponent;
    }

    public Component getCompleteView() {
        return mCompleteComponent;
    }

    public Component getLoadingView() {
        return mLoadingComponent;
    }

    public Component getCustomView() {
        return mCustomComponent;
    }

    private void enterAnimation(Component enterComponent) {
        if (enterComponent == null) {
            return;
        }
        cancelAnimation();
        enterComponent.setVisibility(VISIBLE);
        inAnimator.setTarget(enterComponent);
        inAnimator.start();
    }

    private void exitAnimation(Component exitComponent) {
        if (exitComponent == null) {
            return;
        }
        cancelAnimation();
        exitComponent.setVisibility(VISIBLE);
        outAnimator.setTarget(exitComponent);
        outAnimator.setStateChangedListener(new StateChangeListenerImpl() {
            @Override
            public void onEnd(Animator animator) {
                mCurrentStatus = Status.NONE;
                exitComponent.setVisibility(INVISIBLE);
                outAnimator.setStateChangedListener(null);
                setVisibility(HIDE);
            }
        });
        outAnimator.start();
    }

    private void switchAnimation(Component exitComponent, Component enterComponent) {
        if (exitComponent == null || enterComponent == null) {
            return;
        }
        cancelAnimation();
        // 先执行退出动画，退出动画执行完成后
        exitComponent.setVisibility(VISIBLE);
        outAnimator.setTarget(exitComponent);
        outAnimator.setStateChangedListener(new StateChangeListenerImpl() {
            @Override
            public void onEnd(Animator animator) {
                inAnimator.setTarget(enterComponent);
                exitComponent.setVisibility(INVISIBLE);
                enterComponent.setVisibility(VISIBLE);
                inAnimator.start();
            }
        });
        outAnimator.start();
    }

    private void cancelAnimation() {
        inAnimator.cancel();
        outAnimator.cancel();
    }

    private Component getCurrentView(Status status) {
        if (status == Status.NONE) {
            return null;
        } else if (status == Status.COMPLETE) {
            return mCompleteComponent;
        } else if (status == Status.ERROR) {
            return mErrorComponent;
        } else if (status == Status.LOADING) {
            return mLoadingComponent;
        } else if (status == Status.CUSTOM) {
            return mCustomComponent;
        } else {
            return null;
        }
    }

    private StackLayout.LayoutConfig createLayoutConfig() {
        return new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT);
    }

}
